import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;

public class ExecuteUtil {

	public static String executeArr(String[] command)
			throws IOException {

		ProcessBuilder b = new ProcessBuilder(command);
		StringBuffer ret = new StringBuffer();

		// 표준 에러 출력을 머지 해 출력한다
		b.redirectErrorStream(false);
		Process p;

		p = b.start();

		BufferedReader reader = new BufferedReader(new InputStreamReader(
				p.getInputStream()));
		String line = null;

		// 표준 에러 출력이 표준 출력에 머지 해 출력되므로, 표준 출력만 읽어내면 된다
		while ((line = reader.readLine()) != null) {
			ret.append(line);
		}

		return ret.toString();
	}

	public static String execute(String command, String arg1, String arg2)
			throws IOException {

		// sh 파일이나 기타 FullPathTarget 으로 파일을 실행할 수 있다.
		// 실행파일 이름만으로 실행이 가능하다.
		// 다음과 같은 경우 (실행파일, 옵션, 어규먼트) 형식으로 인식한다.
		// 리눅스를 예를 들자면 rm -rf *.sh 형식이라고 이해하면 된다.
		// ProcessBuilder builder = new ProcessBuilder("rm -rf *.sh");
		// 으로 할 경우 인식을 제대로 못하기 때문에 분리해서 각각 입력한다.
		// ProcessBuilder builder = new ProcessBuilder("rm","-rf","*.sh");
		ProcessBuilder builder = new ProcessBuilder(command, arg1, arg2);
		StringBuffer ret = new StringBuffer();
		Process process = null;

		try {
			// 표준 에러 출력을 머지 해 출력한다
			// builder.redirectErrorStream(false);
			process = builder.start();

			BufferedReader reader = new BufferedReader(new InputStreamReader(
					process.getInputStream()));

			// process.waitFor();
			// 실행한 프로세스가 종료될 때까지 대기한다.
			// 만약 실행한 프로세스가 동기식으로 처리되어야 한다면 사용해야 한다.
			// 하지만 그렇지 않다면 사용해서는 안된다.
			// 예를 들어 데몬이나 서비스 형태의 프로세스를 실행하고자 하는 상황에서
			// 이 명령을 사용하면 해당 프로세스가 종료될 때까지 이 명령을 수행한 프로세스는 진행되지 않는다.
			int i = process.waitFor();

			String line = "";
			// 표준 에러 출력이 표준 출력에 머지 해 출력되므로, 표준 출력만 읽어내면 된다
			while ((line = reader.readLine()) != null) {
				ret.append(line);
			}

			// process.destroy();
		} catch (IOException e) {
			throw new RuntimeException(e);
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		} finally {
			if (null != process) {
				closeQuietly(process.getInputStream());
				closeQuietly(process.getOutputStream());
				closeQuietly(process.getErrorStream());
				// 해당 프로세스를 종료시킨다.
				// 역시 데몬이나 서비스 형태의 프로세스 호출시에는 사용해서는 안된다.
				// 호출하면 해당 프로세스는 종료된다.
				process.destroy();
			} else {
				throw new RuntimeException("Cannot close Process Streams");
			}
		}
		return ret.toString();
	}

	public static void closeQuietly(Writer output) {
		try {
			if (output != null) {
				output.close();
			}
		} catch (IOException ioe) {
			// ignore
		}
	}

	public static void closeQuietly(Reader output) {
		try {
			if (output != null) {
				output.close();
			}
		} catch (IOException ioe) {
			// ignore
		}
	}

	public static void closeQuietly(InputStream output) {
		try {
			if (output != null) {
				output.close();
			}
		} catch (IOException ioe) {
			// ignore
		}
	}

	public static void closeQuietly(OutputStream output) {
		try {
			if (output != null) {
				output.close();
			}
		} catch (IOException ioe) {
			// ignore
		}
	}

	/*
	 * 실행 예제 : 리눅스와, 윈도우 환경에 따라서 다르게 동작하도록 작업해둡니다.
	 */
	public static void callExecute(String util, String parameters) {
		// OS 구분하여 명령어 처리 - 로컬(window) Dos 작업환경을 위해
		String osType = "unix";
		if (System.getProperty("os.name").toLowerCase().indexOf("win") >= 0) {
			osType = "window";
		}

		String retail_size = "";
		
		// 윈도우와 리눅스 둘다 동작하도록 작업.
		try {
			if (osType.equals("window")) {
				
//				String[] param = parameters.split("\" \"");
				
//				String cmd[] = new String[param.length + 1];
				String cmd[] = new String[2];
				cmd[0] = util;
				cmd[1] = parameters;
				
//				// 파라미터 갯수 만큼 설정
//				for(int i = 1; i < cmd.length; i++) {
//					cmd[i] = param[i-1];
//				}
			
				retail_size = ExecuteUtil.executeArr(cmd);			
			} else {
				retail_size = ExecuteUtil.execute(util,	parameters, "");
			}
			
			System.out.println("retail_size: " + retail_size);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
